package org.harsh.transmission.controller;

import java.io.File;
import java.io.IOException;
import java.util.*;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.CharsetUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.CxSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.tbxt.domain.BizSystem;
import com.ruoyi.tbxt.service.IBizSysService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.harsh.common.Config;
import org.harsh.common.Util;
import org.harsh.dispatch.NodeStatusCheckTask;
import org.harsh.transmission.domain.TransReceiver;
import org.harsh.transmission.domain.TransTask;
import org.harsh.transmission.service.ITransReceiverService;
import org.harsh.transmission.service.ITransTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import org.harsh.transmission.domain.TransMsg;
import org.harsh.transmission.service.ITransMsgService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 传输消息Controller
 * 
 * @author liuhaibo
 * @date 2024-08-25
 */
@Controller
@RequestMapping("/transmission/msg")
public class TransMsgController extends BaseController
{
    private String prefix = "transmission/msg";

    class MsgModel {
        private String taskType;
        private String receivers;
        private String recvAddr;
        private int recvPort;
        private String msgData;
        private String msgFiles;

        public MsgModel(String taskType, String receivers, String recvAddr, int recvPort, String msgData, String msgFiles) {
            this.taskType = taskType;
            this.receivers = receivers;
            this.recvAddr = recvAddr;
            this.recvPort = recvPort;
            this.msgData = msgData;
            this.msgFiles = msgFiles;
        }

        public String getTaskType() {
            return taskType;
        }

        public void setTaskType(String taskType) {
            this.taskType = taskType;
        }

        public String getReceivers() {
            return receivers;
        }

        public void setReceivers(String receivers) {
            this.receivers = receivers;
        }

        public String getRecvAddr() {
            return recvAddr;
        }

        public void setRecvAddr(String recvAddr) {
            this.recvAddr = recvAddr;
        }

        public int getRecvPort() {
            return recvPort;
        }

        public void setRecvPort(int recvPort) {
            this.recvPort = recvPort;
        }

        public String getMsgData() {
            return msgData;
        }

        public void setMsgData(String msgData) {
            this.msgData = msgData;
        }

        public String getMsgFiles() {
            return msgFiles;
        }

        public void setMsgFiles(String msgFiles) {
            this.msgFiles = msgFiles;
        }
    }

    @Autowired
    private ITransMsgService transMsgService;
    @Autowired
    private ITransReceiverService transReceiverService;
    @Autowired
    private ITransTaskService transTaskService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IBizSysService bizSysService;

    @Autowired
    private ISysDictDataService dictDataService;

    @RequiresPermissions("transmission:msg:view")
    @GetMapping()
    public String msg()
    {
        return prefix + "/msg";
    }

    /**
     * 查询传输消息列表
     */
    @RequiresPermissions("transmission:msg:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(TransMsg transMsg)
    {
        startPage();
        SysUser currentUser = ShiroUtils.getSysUser();
        if(!currentUser.isAdmin()) {
            // 若不为管理员，则加上过滤条件
            transMsg.setFromId(currentUser.getUserId());
        }
        List<TransMsg> list = transMsgService.selectTransMsgList(transMsg);
        return getDataTable(list);
    }

    /**
     * 查询传输消息列表
     */
    @RequiresPermissions("transmission:msg:list")
    @PostMapping("/listNodeMsg")
    @ResponseBody
    public TableDataInfo listNodeMsg()
    {
        startPage();
        SysUser currentUser = ShiroUtils.getSysUser();
//        long nodeId = currentUser.getDeptId();
//        TransTask task = new TransTask();
//        task.setRecvNode(nodeId);
//        task.set
//        transTaskService.selectTransTaskList()
//        if(!currentUser.isAdmin()) {
//            // 若不为管理员，则加上过滤条件
//            transMsg.setFromId(currentUser.getUserId());
//        }

        List<TransMsg> list = transMsgService.selectTransMsgList(null);
        return getDataTable(list);
    }



    /**
     * 导出传输消息列表
     */
    @RequiresPermissions("transmission:msg:export")
    @Log(title = "导出数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(TransMsg transMsg)
    {
        List<TransMsg> list = transMsgService.selectTransMsgList(transMsg);
        ExcelUtil<TransMsg> util = new ExcelUtil<TransMsg>(TransMsg.class);
        return util.exportExcel(list, "传输消息数据");
    }

    /**
     * 新增传输消息
     */
    @GetMapping("/add")
    public String add(ModelMap mmap)
    {
        SysDept tmp = new SysDept();
        tmp.setParentId(100l);
        SysUser currentUser = ShiroUtils.getSysUser();
        long curDeptId = currentUser.getDeptId();
        List<SysDept> depts = sysDeptService.selectDeptList(tmp);
        List<SysUser> users = sysUserService.selectUserList(new SysUser());

        List<CxSelect> cxList = new ArrayList<CxSelect>();

        for(SysDept dept : depts) {
            // 过滤本地节点
            //if(curDeptId != dept.getDeptId().longValue()) {
                CxSelect cxSelect = new CxSelect();
                cxSelect.setN(dept.getDeptName());
                int delay = NodeStatusCheckTask.getDelay(dept.getDeptId().longValue());
                cxSelect.setV(dept.getDeptId() + "("+delay+" ms)");

                List<CxSelect> tmList = new ArrayList<CxSelect>();
                for (SysUser user : users) {
                    if (user.getDeptId().longValue() == dept.getDeptId().longValue() && user.getUserId().longValue() != currentUser.getUserId().longValue()) {
                        tmList.add(new CxSelect(user.getUserId() + "", user.getUserName()));
                    }
                }
                cxSelect.setS(tmList);
                cxList.add(cxSelect);
            //}
        }

        mmap.put("data", JSON.toJSON(cxList));
        return prefix + "/add";
    }

    /**
     * 新增保存传输消息
     */
    @RequiresPermissions("transmission:msg:add")
    @Log(title = "发布数据", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(TransMsg transMsg)
    {
        return toAjax(transMsgService.insertTransMsg(transMsg));
    }


    @RequiresPermissions("transmission:msg:add")
    @Log(title = "发布数据", businessType = BusinessType.INSERT)
    @PostMapping("/addSave")
    @ResponseBody
    public AjaxResult addSaveMsg(MsgModel transModel) {
        String msgData = transModel.getMsgData();
        String receivers = transModel.getReceivers();
        String taskType = transModel.getTaskType();
        String msgFiles = transModel.getMsgFiles();
        String recvAddr = transModel.getRecvAddr();
        int recvPort = transModel.getRecvPort();

        SysDept sysDept = sysDeptService.loadLocalDept();
        SysUser currentUser = ShiroUtils.getSysUser();

        if("0".equals(taskType) || "3".equals(taskType)) {
            // 单播 或 单向传输
            Set<Long> userList = new HashSet();
            Set<Long> deptList = new HashSet();
            Map<Long, Long> sysDeptSet = new HashMap<>();
            for(String recvs : receivers.split(":")) {
                long userId = Long.parseLong(recvs);
                SysUser tmpUser = sysUserService.selectUserById(userId);
                //if(tmpUser.getDeptId().longValue() != sysDept.getDeptId().longValue()) {
                    userList.add(userId);
                    deptList.add(tmpUser.getDeptId());
                    sysDeptSet.put(userId, tmpUser.getDeptId());
                //}
            }

            if(msgData != null && !"".equals(msgData)) {
                TransMsg transMsg = new TransMsg();
                byte[] msgBytes = msgData.getBytes(Config.DEFAULT_CHARSET);
                long msgId = (long)Math.abs(UUID.randomUUID().hashCode());
                transMsg.setMsgId(msgId);
                transMsg.setTransType(Long.parseLong(taskType));
                transMsg.setMsgType(0l);
                transMsg.setMsgSize((long)msgBytes.length);
                transMsg.setFromNode(sysDept.getDeptId());
                transMsg.setFromType(0l);
                transMsg.setFromId(currentUser.getUserId());

                String msgMd5 = null;
                try {
                    msgMd5 = Util.byteArrMD5Str(msgBytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                transMsg.setMsgMd5(msgMd5);
                transMsg.setMsgData(msgData);
                transMsgService.insertTransMsg(transMsg);

                for(long userId : userList) {
                    TransReceiver receiver = new TransReceiver();
                    receiver.setMsgId(msgId);
                    // 接收对象为用户
                    receiver.setRecvType(1l);
                    receiver.setRecvId(userId);
                    receiver.setRecvNode(sysDeptSet.get(userId));
                    transReceiverService.insertTransReceiver(receiver);
                }

                for(long deptId : deptList) {
                    if(deptId != sysDept.getDeptId().longValue()){
                        // 非本节点需要添加分发任务
                        TransTask task = new TransTask();
                        task.setMsgId(msgId);
                        task.setTaskPriority(10l);
                        task.setTaskType(Long.parseLong(taskType));
                        task.setRecvNode(deptId);
                        task.setTaskStatus(0l);
                        transTaskService.insertTransTask(task);
                    }
                }
            }
            if(msgFiles != null && !"".equals(msgFiles)) {
                for(String str : msgFiles.split(":")) {
                    TransMsg transMsg = new TransMsg();
                    long msgId = (long)Math.abs(UUID.randomUUID().hashCode());
                    transMsg.setMsgId(msgId);
                    transMsg.setTransType(Long.parseLong(taskType));
                    transMsg.setMsgType(1l);

                    String localPath = RuoYiConfig.getProfile();
                    // 数据库资源地址
                    String downloadPath = localPath + StringUtils.substringAfter(str, Constants.RESOURCE_PREFIX);
                    File f = new File(downloadPath);
                    transMsg.setMsgSize(f.length());
                    transMsg.setFromNode(sysDept.getDeptId());
                    transMsg.setFromType(0l);
                    transMsg.setFromId(currentUser.getUserId());
                    try {
                        transMsg.setMsgMd5(Util.fileMD5Str(f));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    transMsg.setMsgData(str);
                    transMsgService.insertTransMsg(transMsg);

                    for(long userId : userList) {
                        TransReceiver receiver = new TransReceiver();
                        receiver.setMsgId(msgId);
                        // 接收对象为用户
                        receiver.setRecvType(1l);
                        receiver.setRecvId(userId);
                        receiver.setRecvNode(sysDeptSet.get(userId));
                        transReceiverService.insertTransReceiver(receiver);
                    }

                    for(long deptId : deptList) {
                        if(deptId != sysDept.getDeptId().longValue()) {
                            TransTask task = new TransTask();
                            task.setMsgId(msgId);
                            task.setTaskPriority(10l);
                            task.setTaskType(Long.parseLong(taskType));
                            task.setRecvNode(deptId);
                            task.setTaskStatus(0l);
                            transTaskService.insertTransTask(task);
                        }
                    }
                }
            }
        } else {
            // 组播或广播
            if(msgData != null && !"".equals(msgData)) {
                TransMsg transMsg = new TransMsg();
                byte[] msgBytes = msgData.getBytes(Config.DEFAULT_CHARSET);
                long msgId = (long) Math.abs(UUID.randomUUID().hashCode());
                transMsg.setMsgId(msgId);
                transMsg.setTransType(Long.parseLong(taskType));
                transMsg.setMsgType(0l);
                transMsg.setMsgSize((long) msgBytes.length);
                transMsg.setFromNode(sysDept.getDeptId());
                transMsg.setFromType(0l);
                transMsg.setFromId(currentUser.getUserId());
                String msgMd5 = null;
                try {
                    msgMd5 = Util.byteArrMD5Str(msgBytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                transMsg.setMsgMd5(msgMd5);
                transMsg.setMsgData(msgData);
                transMsgService.insertTransMsg(transMsg);

                TransReceiver receiver = new TransReceiver();
                receiver.setMsgId(msgId);
                receiver.setRecvNode(0l);
                // 接收对象为组播或广播节点
                receiver.setRecvType(0l);
                transReceiverService.insertTransReceiver(receiver);

                TransTask task = new TransTask();
                task.setMsgId(msgId);
                task.setTaskPriority(10l);
                task.setTaskType(Long.parseLong(taskType));
                task.setRecvNode(0l);
                task.setRecvAddr(recvAddr);
                task.setRecvPort(recvPort);
                task.setTaskStatus(0l);
                transTaskService.insertTransTask(task);
            }
            if(msgFiles != null && !"".equals(msgFiles)) {
                for(String str : msgFiles.split(":")) {
                    TransMsg transMsg = new TransMsg();
                    long msgId = (long) Math.abs(UUID.randomUUID().hashCode());
                    transMsg.setMsgId(msgId);
                    transMsg.setTransType(Long.parseLong(taskType));
                    transMsg.setMsgType(1l);
                    //profile/upload/2024/08/30/index_20240830120204A001.css

                    String localPath = RuoYiConfig.getProfile();
                    // 数据库资源地址
                    String downloadPath = localPath + StringUtils.substringAfter(str, Constants.RESOURCE_PREFIX);
                    File f = new File(downloadPath);
                    transMsg.setMsgSize(f.length());
                    transMsg.setFromNode(sysDept.getDeptId());
                    transMsg.setFromType(0l);
                    transMsg.setFromId(currentUser.getUserId());
                    try {
                        transMsg.setMsgMd5(Util.fileMD5Str(f));
                    } catch (IOException e) {
                        e.printStackTrace();
                        transMsg.setMsgMd5("");
                    }
                    transMsg.setMsgData(str);
                    transMsgService.insertTransMsg(transMsg);

                    TransReceiver receiver = new TransReceiver();
                    receiver.setMsgId(msgId);
                    // 接收对象为组播或广播节点
                    receiver.setRecvType(0l);
                    receiver.setRecvNode(0l);
                    transReceiverService.insertTransReceiver(receiver);

                    TransTask task = new TransTask();
                    task.setMsgId(msgId);
                    task.setTaskPriority(10l);
                    task.setTaskType(Long.parseLong(taskType));
                    task.setRecvNode(0l);
                    task.setRecvAddr(recvAddr);
                    task.setRecvPort(recvPort);
                    task.setTaskStatus(0l);
                    transTaskService.insertTransTask(task);
                }
            }
        }

        return toAjax(1);
    }

    /**
     * 修改传输消息
     */
    @RequiresPermissions("transmission:msg:edit")
    @GetMapping("/edit/{msgId}")
    public String edit(@PathVariable("msgId") Long msgId, ModelMap mmap)
    {
        TransMsg transMsg = transMsgService.selectTransMsgByMsgId(msgId);
        mmap.put("transMsg", transMsg);
        return prefix + "/edit";
    }

    /**
     * 修改保存传输消息
     */
    @RequiresPermissions("transmission:msg:edit")
    @Log(title = "传输消息", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(TransMsg transMsg)
    {
        return toAjax(transMsgService.updateTransMsg(transMsg));
    }

    /**
     * 删除传输消息
     */
    @RequiresPermissions("transmission:msg:remove")
    @Log(title = "传输消息", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        return toAjax(transMsgService.deleteTransMsgByMsgIds(ids));
    }
}
